using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace MKDS_Course_Editor
{
    public partial class nclr_e : Form
    {
        int r = 255;
        int g = 255;
        int b = 255;
        List<Color> colors = new List<Color>();
        bool bpp8_ = false;
        uint unknown1;
        public nclr_e(Color[] c, bool bpp8, uint unknown)
        {
            InitializeComponent();
            colors.AddRange(c);
            bpp8_ = bpp8;
            unknown1 = unknown;
            if (bpp8 == true)
            {
                toolStripComboBox1.SelectedIndex = 1;
            }
        }
        public nclr_e()
        {

        }
        private void textBox1_TextChanged(object sender, EventArgs e)
        {
            try { r = Convert.ToInt32(textBox1.Text); if (r > 255) { r = 255; textBox1.Text = r.ToString(); } }
            catch { textBox1.Text = r.ToString(); };
            trackBar1.Value = r;
            panel2.BackColor = Color.FromArgb(r, g, b);
            p.BackColor = panel2.BackColor;
            p.PanelColor = panel2.BackColor;
        }

        private void textBox2_TextChanged(object sender, EventArgs e)
        {
            try { g = Convert.ToInt32(textBox2.Text); if (g > 255) { g = 255; textBox2.Text = g.ToString(); } }
            catch { textBox2.Text = g.ToString(); };
            trackBar2.Value = g;
            panel2.BackColor = Color.FromArgb(r, g, b);
            p.BackColor = panel2.BackColor;
            p.PanelColor = panel2.BackColor;
        }

        private void textBox3_TextChanged(object sender, EventArgs e)
        {
            try { b = Convert.ToInt32(textBox3.Text); if (b > 255) { b = 255; textBox3.Text = b.ToString(); } }
            catch { textBox3.Text = b.ToString(); };
            trackBar3.Value = b;
            panel2.BackColor = Color.FromArgb(r, g, b);
            p.BackColor = panel2.BackColor;
            p.PanelColor = panel2.BackColor;
        }

        private void trackBar1_Scroll(object sender, EventArgs e)
        {
            r = trackBar1.Value;
            textBox1.Text = r.ToString();
            panel2.BackColor = Color.FromArgb(r, g, b);
            p.BackColor = panel2.BackColor;
            p.PanelColor = panel2.BackColor;
        }

        private void trackBar2_Scroll(object sender, EventArgs e)
        {
            g = trackBar2.Value;
            textBox2.Text = g.ToString();
            panel2.BackColor = Color.FromArgb(r, g, b);
            p.BackColor = panel2.BackColor;
            p.PanelColor = panel2.BackColor;
        }

        private void trackBar3_Scroll(object sender, EventArgs e)
        {
            b = trackBar3.Value;
            textBox3.Text = b.ToString();
            panel2.BackColor = Color.FromArgb(r, g, b);
            p.BackColor = panel2.BackColor;
            p.PanelColor = panel2.BackColor;
        }
        MKDS_Course_Editor.nlcr_viewer.ColorPanel p = new MKDS_Course_Editor.nlcr_viewer.ColorPanel();
        private void nlcr_viewer1_ColorClicked(object sender, MouseEventArgs e)
        {
            p = (MKDS_Course_Editor.nlcr_viewer.ColorPanel)sender;
            r = p.BackColor.R;
            g = p.BackColor.G;
            b = p.BackColor.B;
            trackBar1.Value = r;
            trackBar2.Value = g;
            trackBar3.Value = b;
            textBox1.Text = r.ToString();
            textBox2.Text = g.ToString();
            textBox3.Text = b.ToString();
        }

        private void nclr_e_Load(object sender, EventArgs e)
        {
            nlcr_viewer1.bpp8 = bpp8_;
            nlcr_viewer1.Colors = colors;
        }

        private void nlcr_viewer1_KeyUp(object sender, KeyEventArgs e)
        {
            // MessageBox.Show(e.Control.ToString() + ", " + e.KeyCode.ToString());
            //if (e.Control && e.KeyCode == Keys.C)
            //{
            //    Clipboard.SetText(ColorTranslator.ToHtml(panel2.BackColor));
            //}
            //if (e.Control && e.KeyCode == Keys.V)
            //{
            //    panel2.BackColor = ColorTranslator.FromHtml(Clipboard.GetText());
            //}

        }

        private void nlcr_viewer1_KeyDown(object sender, KeyEventArgs e)
        {
            //MessageBox.Show(e.Control.ToString() + ", " + e.KeyCode.ToString());
            //if (e.Control && e.KeyCode == Keys.C)
            //{
            //    Clipboard.SetText(ColorTranslator.ToHtml(panel2.BackColor));
            //}
            //else if (e.)
            //{
            //    panel2.BackColor = ColorTranslator.FromHtml(Clipboard.GetText());
            //}
        }

        private void toolStripButton1_Click(object sender, EventArgs e)
        {
            Clipboard.SetText(ColorTranslator.ToHtml(panel2.BackColor));
        }

        private void toolStripButton2_Click(object sender, EventArgs e)
        {
            panel2.BackColor = ColorTranslator.FromHtml(Clipboard.GetText());
            p.BackColor = panel2.BackColor;
            p.PanelColor = panel2.BackColor;
        }

        private void toolStripButton5_Click(object sender, EventArgs e)
        {
            if (saveFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK
                && saveFileDialog1.FileName.Length > 0)
            {
                EndianBinaryWriter er = new EndianBinaryWriter(File.Create(saveFileDialog1.FileName), Endianness.LittleEndian);
                er.Write("RLCN", Encoding.ASCII, false);
                er.Write(new byte[] { 0xFF, 0xFE, 0x00, 0x01 }, 0, 4);
                Color[] c3 = nlcr_viewer1.getPallete();
                List<Int16> palbyte = new List<Int16>();
                for(int i = 0; i < c3.Length; i++)
        {
            Color color = c3[i];
            int nc = 0;
            nc = encodeColor(color.ToArgb(), BGR555);
            palbyte.Add((Int16)nc);
        }
                er.Write(40 + (palbyte.Count*2));
                er.Write((short)0x10);
                er.Write((short)1);

                er.Write(new byte[] { 0x54, 0x54, 0x4C, 0x50 }, 0, 4);
                er.Write(24 + (palbyte.Count*2));
                if (bpp8_)
                {
                    er.Write((short)4);
                }
                else
                {
                    er.Write((short)3);
                }
                er.Write((ushort)unknown1);
                er.Write(new byte[] { 0x00, 0x00, 0x00, 0x00 }, 0, 4);
                er.Write(palbyte.Count*2);
                er.Write(16);
                er.Write(palbyte.ToArray(), 0, palbyte.Count);
                er.Close();
            }
        }
        public int decodeColor(int value, CColorFormat format)
    {
        int[] res = format.getResolution();
        int rgb = Convert.ToInt32(0xff000000);
        int shift = 0;
        int length = res.Length / 2;
        for(int i = 0; i < length; i++)
        {
            int mode = res[length - i - 1];
            int nshift = res[length * 2 - i - 1];
            int mult = shiftList[nshift][1];
            int and = shiftList[nshift][0];
            int n = (value >> shift & and) * mult;
            switch(mode)
            {
            case 0: // '\0'
                rgb |= n << 24;
                break;

            case 1: // '\001'
                rgb |= n << 16;
                break;

            case 2: // '\002'
                rgb |= n << 8;
                break;

            case 3: // '\003'
                rgb |= n;
                break;

            case 4: // '\004'
                rgb = n << 16 | n << 8 | n;
                break;
            }
            shift += nshift;
        }

        return rgb;
    }
        public CColorFormat BGR555 = new CColorFormat("BGR555", 10, 16, new int[] {
        3, 2, 1, 5, 5, 5
    });

        public int encodeColor(int value, CColorFormat format)
        {
            int[] res = format.getResolution();
            int rgb = 0;
            int shift = 0;
            int length = res.Length / 2;
            for (int i = 0; i < length; i++)
            {
                int mode = res[length - i - 1];
                int nshift = res[length * 2 - i - 1];
                int mult = shiftList[nshift][1];
                int and = shiftList[nshift][0];
                int n = 0;
                switch (mode)
                {
                    case 0: // '\0'
                        n = value >> 24 & 0xff;
                        break;

                    case 1: // '\001'
                        n = value >> 16 & 0xff;
                        break;

                    case 2: // '\002'
                        n = value >> 8 & 0xff;
                        break;

                    case 3: // '\003'
                        n = value & 0xff;
                        break;

                    case 4: // '\004'
                        n = value & 0xff;
                        break;
                }
                rgb |= (n / mult & and) << shift;
                shift += nshift;
            }

            return rgb;
        }

        public int[][] shiftList = new int[][] { new int[] { 0, 0 }, new int[] { 1, 255 }, new int[] { 3, 85 }, new int[] { 7, 36 }, new int[] { 15, 17 }, new int[] { 31, 8 }, new int[] { 63, 4 }, new int[] { 127, 2 }, new int[] { 255, 1 } };
        public class CColorFormat
        {

            public CColorFormat(String name, int id, int depth, int[] res)
            {
                this.name = name;
                this.id = id;
                this.depth = depth;
                this.res = res;
            }

            public String toString()
            {
                return getName();
            }

            public String getName()
            {
                return name;
            }

            public int getId()
            {
                return id;
            }

            public int getDepth()
            {
                return depth;
            }

            public int[] getResolution()
            {
                return res;
            }

            public int getWidth(int field)
            {
                for (int i = 0; i < res.Length / 2; i++)
                    if (res[i] == field)
                        return res[i + res.Length / 2];

                return 0;
            }

            private String name;
            private int id;
            private int depth;
            private int[] res;
        }

        private void toolStripButton3_Click(object sender, EventArgs e)
        {
            nlcr_viewer1.addColor();
        }

        private void toolStripButton4_Click(object sender, EventArgs e)
        {
            nlcr_viewer1.removeColor();
        }

        private void toolStripButton6_Click(object sender, EventArgs e)
        {
            if (saveFileDialog2.ShowDialog() == System.Windows.Forms.DialogResult.OK
                && saveFileDialog2.FileName.Length > 0)
            {
                EndianBinaryWriter er = new EndianBinaryWriter(File.Create(saveFileDialog2.FileName), Endianness.LittleEndian);
                er.Write("RIFF", Encoding.ASCII, false);
                Color[] c3 = nlcr_viewer1.getPallete();
                er.Write(0xC+(c3.Length*4));
                er.Write("PAL data", Encoding.ASCII, false);
                er.Write((c3.Length * 4));
                er.Write((Int16)768);
                er.Write((Int16)c3.Length);
                for (int i = 0; i < c3.Length; i++)
                {
                    er.Write((sbyte)c3[i].R);
                    er.Write((sbyte)c3[i].G);
                    er.Write((sbyte)c3[i].B);
                    er.Write((sbyte)0);
                }
                er.Close();
            }
        }

        private void toolStripButton9_Click(object sender, EventArgs e)
        {
            if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK
                && openFileDialog1.FileName.Length > 0)
            {
                EndianBinaryReader er = new EndianBinaryReader(File.OpenRead(openFileDialog1.FileName), Endianness.LittleEndian);
                er.ReadBytes(0x16);
                int count = er.ReadInt16();
                List<Color> col = new List<Color>();
                for (int i = 0; i < count; i++)
                {
                    col.Add(Color.FromArgb(er.ReadByte(), er.ReadByte(), er.ReadByte()));
                    er.ReadSByte();
                }
                er.Close();
                nlcr_viewer1.Colors.Clear();
                nlcr_viewer1.Colors = col;
            }
        }

        private void toolStripComboBox1_Click(object sender, EventArgs e)
        {

        }

        private void toolStripComboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            nlcr_viewer1.bpp8 = toolStripComboBox1.SelectedIndex == 0 ? false : true;
            bpp8_ = toolStripComboBox1.SelectedIndex == 0 ? false : true;
        }

        private void toolStripButton10_Click(object sender, EventArgs e)
        {
            Color[] p = nlcr_viewer1.getPallete();
            if (p.Length >= 16)
            {
                List<Color> p2 = new List<Color>();
                p2.AddRange(p);
                p2.AddRange(p.ToList().GetRange(0, 16));
                nlcr_viewer1.Colors=p2;
            }
            else
            {
                List<Color> p2 = new List<Color>();
                p2.AddRange(p);
                for (int i = 0; i < 16; i++)
                {
                    p2.Add(Color.Black);
                }
                nlcr_viewer1.Colors=p2;
            }
        }

        private void toolStripButton11_Click(object sender, EventArgs e)
        {
            Color[] p = nlcr_viewer1.getPallete();
            List<Color> p2 = new List<Color>();
            p2.AddRange(p);
            for (int i = 0; i < 16; i++)
            {
                p2.Add(Color.Black);
            }
            nlcr_viewer1.Colors = p2;
        }
    }
}
